import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * Class that maintains a histogram of phrases.
 * It supports adding new phrases and updating
 * counts of already existing phrases
 * @author gabriel
 *
 */
public class PhraseHistogram {

    /**
     * Map to store the phrases internally.
     * Allow us to maintain a mapping of a phrase entry
     * to itself, so that the key can be used to search
     */
    HashMap phraseMap;
    /**
     * the path of file for which this histogram was built 
     */
    String filename;
    
    /**
     * Statistical information about the file for which this histogram was built
     */
    public int numLines;
    public int numChars;
    public int numWords;
    
    /**
     * Constructor
     *
     */
    public PhraseHistogram() {
        this.phraseMap = new HashMap();
        filename=null;
        
    }
    public Iterator getPhraseIterator(){
    	return phraseMap.values().iterator();
    }
    /**
     * returns the file path
     * @return
     */
    public String getFileName()
    {
    	return filename;
    }
    
    public PhraseHistogram(String filename) {
        this.phraseMap = new HashMap();
        this.filename=filename;
    }

    /**
     * Test if a phrase is new, i.e. it is not
     * in this object
     * @param phrase the phrase to check
     * @return true if the phrase does not exist in the histogram
     */
    public boolean checkIfNew(PhraseObject phrase) {
        return !this.phraseMap.containsKey(phrase);
    }
    
    /**
     * Checks if a phrase is in the table. If so, it
     * updates its count, if not it adds a new instance to
     * the table with count 1
     * @param phrase the phrase to check
     * @return true if the phrase was found
     */
    public boolean checkPhraseAndUpdate(PhraseObject phrase) {
        boolean ret = false;
        Object obj = this.phraseMap.get(phrase);
        if (obj == null) {
            PhraseEntry entry = new PhraseEntry();
            entry.copyPhrase(phrase);
            entry.increment();
            this.phraseMap.put(entry, entry);
        } else {
            ret = true;
            ((PhraseEntry) obj).increment();
            Iterator iter=phrase.lineNumbers.iterator();
            while(iter.hasNext())
            ((PhraseEntry) obj).lineNumbers.add(iter.next());
        }
        return ret;
    }
    
    /**
     * Prints out the histogram.
     * @param threshold The minimum number of occurences to have seen
     * before we print a phrase
     *
     */
    public void printHisto(int threshold) {
        List sortList = new LinkedList(this.phraseMap.values());
        Collections.sort(sortList);
        ListIterator iter = sortList.listIterator();
        while (iter.hasNext()) {
            PhraseEntry phrase = (PhraseEntry) iter.next();
            if (phrase.getCount() >= threshold) {
                System.out.println(phrase);
            }
        }
    }

}
